﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Web7.Dispose;
using Web7.Ioc.DemandBuilders;

namespace Web7.Ioc
{
    /// <summary>
    /// 当在派生类中实现时，提供登记服务与特定的依赖管理容器.
    /// </summary>
    public abstract class AbstractContainerBuilder : IWeb7ContainerBuilder
    {
        protected AbstractContainerBuilder()
        {
            AfterReset += InitDefaults;
            Context = new DefaultBuilderContext();
        }

        /// <summary>添加需求的依赖项到容器中，并指示它来注册它的依赖。</summary>
        /// <param name="demandBuilder">需求建立者</param>
        /// <returns>.</returns>
        public IWeb7ContainerBuilder AddDependencyDemandBuilder(IDependencyDemandBuilder demandBuilder)
        {
            //Mandate.ParameterNotNull(demandBuilder, "demandBuilder");//todo:验证参数

            using (DisposableTimer.TraceDuration<AbstractContainerBuilder>("Start AddDependencyDemandBuilder " + demandBuilder.GetType().Name, "End AddDependencyDemandBuilder"))
            {
                demandBuilder.Build(this, Context);
                return this;
            }
        }

        /// <summary>从程序集中添加依赖需求建设者 <typeparamref name="T"/>.</summary>
        /// <typeparam name="T">根据此类型推断当前所处的程序集</typeparam>
        /// <returns>.</returns>
        public IWeb7ContainerBuilder AddDemandsFromAssemblyOf<T>()
        {
            AddDemandsFromAssemblyOf(typeof(T));
            return this;
        }

        /// <summary>从程序集中添加依赖需求建设者</summary>
        /// <param name="exampleType">根据此类型推断当前所处的程序集</param>
        /// <returns>.</returns>
        public IWeb7ContainerBuilder AddDemandsFromAssemblyOf(Type exampleType)
        {
            //Mandate.ParameterNotNull(exampleType, "exampleType"); //todo:参数验证

            using (DisposableTimer.TraceDuration<AbstractContainerBuilder>("Start AddDemandsFromAssemblyOf", "End AddDemandsFromAssemblyOf"))
            {

                Type[] typesInAssembly = exampleType.Assembly.GetTypes();
                //setup 1: 执行 所有实现了IDpendencyDemandBuilder 的Build方法 
                /* 此方案暂时不添加
                IEnumerable<Type> typesImplementingInterface = typesInAssembly
                    .Where(type => typeof(IDependencyDemandBuilder).IsAssignableFrom(type));

                IEnumerable<IDependencyDemandBuilder> demandBuilders = typesImplementingInterface
                    .Select(component => Activator.CreateInstance(component) as IDependencyDemandBuilder);

                demandBuilders
                    .ToList()
                    .ForEach(x => AddDependencyDemandBuilder(x));
                 */

                //setup 2: 注册实现IDependency等相应接口的类.

                var list = typesInAssembly.Where(t => t.IsClass && !t.IsAbstract && typeof(IDependency).IsAssignableFrom(t) && !t.ContainsGenericParameters).ToList();

                foreach (var t in list)
                {
                    var interfaces = t.GetInterfaces().Where(m => typeof(IDependency)
                                    .IsAssignableFrom(m))
                                    .ToList();

                    foreach (var type in interfaces)
                    {
                        //todo:此流程还需要修改,不把IDependency注册进来？(丁乐）
                        if (typeof(ISingletonDependency).IsAssignableFrom(type))
                        {
                            For(t).KnownAs(type).ScopedAs.Singleton();
                        }
                        else if (typeof(IUnitOfWorkDependency).IsAssignableFrom(type))
                        {
                            //todo:工作区的东西先预留
                        }
                        else if (typeof(ITransientDependency).IsAssignableFrom(type))
                        {
                            For(t).KnownAs(type).ScopedAs.NewInstanceEachTime();
                        }
                        else
                        {
                            For(t).KnownAs(type);
                        }
                    }
                }
                return this;
            }
        }

        public abstract IDependencyRegistrar<object> For(Type type);
        public abstract IDependencyRegistrar<T> For<T>();
        public abstract IDependencyRegistrar<TContract> ForFactory<TContract>(Func<IResolutionContext, TContract> @delegate);

        public IBuilderContext Context { get; protected set; }

        public abstract IDependencyRegistrar<TContract> ForInstanceOfType<TContract>(TContract implementation) where TContract : class;

        /// <summary>
        /// 实例化默认的需求建立者
        /// </summary>
        public void InitDefaults()
        {
            // 注册默认的框架(web7)
            AddDependencyDemandBuilder(new FrameworkSetup());
        }

        /// <summary>
        /// reset前委托
        /// </summary>
        protected Action BeforeReset;
        /// <summary>
        /// reset后委托
        /// </summary>
        protected Action AfterReset;

        protected abstract void PerformReset();

        /// <summary>
        /// reset 容器
        /// </summary>
        public void Reset()
        {
            if (BeforeReset != null)
                BeforeReset.Invoke();
            PerformReset();
            if (AfterReset != null)
                AfterReset.Invoke();
        }

        /// <summary>指定容器，以建立依赖Map</summary>
        /// <returns>An <see cref="IWeb7DependencyResolver"/> 依赖服务接口</returns>
        public abstract IWeb7DependencyResolver Build();
    }
}
